home *** CD-ROM | disk | FTP | other *** search
- /* $Id: pdfutils.c,v 1.11 1994/08/25 04:04:06 mjl Exp $
- * $Log: pdfutils.c,v $
- * Revision 1.11 1994/08/25 04:04:06 mjl
- * Eliminated an unnecessary header file inclusion.
- *
- * Revision 1.10 1994/06/30 18:21:56 mjl
- * All core source files: made another pass to eliminate warnings when using
- * gcc -Wall. Lots of cleaning up: got rid of includes of math.h or string.h
- * (now included by plplot.h), and other minor changes. Now each file has
- * global access to the plstream pointer via extern; many accessor functions
- * eliminated as a result.
- */
-
- /*--------------------------------------------------------------------------*\
-
- pdf_utils.c
-
- Copyright (C) 1992 by Maurice J. LeBrun
-
- This software may be freely copied, modified and redistributed without
- fee provided that this copyright notice is preserved intact on all
- copies and modified copies.
-
- There is no warranty or other guarantee of fitness of this software.
- It is provided solely "as is". The author(s) disclaim(s) all
- responsibility and liability with respect to this software's usage or
- its effect upon hardware or computer systems.
-
- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-
- These functions do the low-level reading/writing of portable data files.
- Data can be written to/read from either a file handle or memory buffer.
- \*--------------------------------------------------------------------------*/
-
- #include "plplotP.h"
-
- static void print_ieeef (void *, void *);
- static int pdf_wrx (const U_CHAR *x, long nitems, PDFstrm *pdfs);
- static int pdf_rdx (U_CHAR *x, long nitems, PDFstrm *pdfs);
-
- static int debug = 0;
-
- /*--------------------------------------------------------------------------*\
- * void pdf_set (string, value)
- *
- * Set an option. Pretty sparse right now but you never know.
- \*--------------------------------------------------------------------------*/
-
- void
- pdf_set(char *option, int value)
- {
- if ( ! strcmp(option, "debug"))
- debug = value;
- }
-
- /*----------------------------------------------------------------------*\
- * pdf_fopen()
- *
- * Initializes a PDFstrm for a file oriented device.
- * Used exactly like fopen().
- \*----------------------------------------------------------------------*/
-
- PDFstrm *
- pdf_fopen(char *filename, char *mode)
- {
- PDFstrm *pdfs;
-
- dbug_enter("pdf_fopen");
-
- pdfs = (PDFstrm *) malloc(sizeof(PDFstrm));
-
- if (pdfs != NULL) {
- pdfs->buffer = NULL;
-
- pdfs->file = fopen(filename, mode);
- if (pdfs->file == NULL) {
- pdf_close(pdfs);
- pdfs = NULL;
- }
- }
-
- return pdfs;
- }
-
- /*----------------------------------------------------------------------*\
- * pdf_bopen()
- *
- * Initializes a PDFstrm for reading/writing to a memory buffer.
- * If buffer is NULL, a standard buffer is allocated.
- \*----------------------------------------------------------------------*/
-
- PDFstrm *
- pdf_bopen(U_CHAR *buffer, long bufmax)
- {
- PDFstrm *pdfs;
-
- dbug_enter("pdf_bopen");
-
- pdfs = (PDFstrm *) malloc(sizeof(PDFstrm));
-
- if (pdfs != NULL) {
- pdfs->file = NULL;
- pdfs->bp = 0;
-
- if (buffer == NULL) {
- if (bufmax > 0)
- pdfs->bufmax = bufmax;
- else
- pdfs->bufmax = 2048;
-
- pdfs->buffer = (U_CHAR *) malloc(pdfs->bufmax);
- if (pdfs->buffer == NULL) {
- pdf_close(pdfs);
- pdfs = NULL;
- }
- }
- else {
- pdfs->bufmax = bufmax;
- pdfs->buffer = buffer;
- }
- }
-
- return pdfs;
- }
-
- /*----------------------------------------------------------------------*\
- * pdf_finit()
- *
- * Initializes a PDFstrm for a file oriented device.
- * Like pdf_fopen() but an existing file handle is specified.
- \*----------------------------------------------------------------------*/
-
- PDFstrm *
- pdf_finit(FILE *file)
- {
- PDFstrm *pdfs;
-
- dbug_enter("pdf_finit");
-
- pdfs = (PDFstrm *) malloc(sizeof(PDFstrm));
-
- if (pdfs != NULL) {
- pdfs->buffer = NULL;
- pdfs->file = file;
- }
-
- return pdfs;
- }
-
- /*----------------------------------------------------------------------*\
- * pdf_close()
- *
- * Closes a PDFstrm.
- * Used exactly like fclose().
- \*----------------------------------------------------------------------*/
-
- int
- pdf_close(PDFstrm *pdfs)
- {
- dbug_enter("pdf_close");
-
- if (pdfs != NULL) {
- if (pdfs->file != NULL)
- fclose(pdfs->file);
-
- else if (pdfs->buffer != NULL)
- free ((void *) pdfs->buffer);
-
- free((void *) pdfs);
- }
- return 0;
- }
-
- /*----------------------------------------------------------------------*\
- * int pdf_putc()
- *
- * Writes a single character.
- \*----------------------------------------------------------------------*/
-
- int
- pdf_putc(int c, PDFstrm *pdfs)
- {
- int result = EOF;
-
- if (pdfs->file != NULL) {
- result = putc(c, pdfs->file);
- pdfs->bp++;
- }
- else if (pdfs->buffer != NULL) {
- if (pdfs->bp >= pdfs->bufmax) {
- pdfs->bufmax += 512;
- #ifdef DEBUG
- fprintf(stderr,
- "pdf_putc: Increasing buffer to %d bytes\n",
- pdfs->bufmax);
- #endif
- pdfs->buffer = (U_CHAR *)
- realloc((void *) pdfs->buffer, pdfs->bufmax);
- }
- pdfs->buffer[pdfs->bp++] = c;
- result = c;
- }
- else
- plexit("pdf_putc: Illegal operation");
-
- return result;
- }
-
- /*----------------------------------------------------------------------*\
- * int pdf_getc()
- *
- * Reads a single character.
- \*----------------------------------------------------------------------*/
-
- int
- pdf_getc(PDFstrm *pdfs)
- {
- int result = EOF;
-
- if (pdfs->file != NULL) {
- result = getc(pdfs->file);
- pdfs->bp++;
- }
- else if (pdfs->buffer != NULL) {
- if (pdfs->bp < pdfs->bufmax)
- result = pdfs->buffer[pdfs->bp++];
- }
- else
- plexit("pdf_getc: Illegal operation");
-
- return result;
- }
-
- /*----------------------------------------------------------------------*\
- * int pdf_ungetc()
- *
- * Push back the last command read.
- \*----------------------------------------------------------------------*/
-
- int
- pdf_ungetc(int c, PDFstrm *pdfs)
- {
- int result = EOF;
-
- if (pdfs->file != NULL) {
- result = ungetc(c, pdfs->file);
- if (pdfs->bp > 0)
- pdfs->bp--;
- }
- else if (pdfs->buffer != NULL) {
- if (pdfs->bp > 0) {
- pdfs->buffer[--pdfs->bp] = c;
- result = c;
- }
- }
- else
- plexit("pdf_ungetc: Illegal operation");
-
- return result;
- }
-
- /*----------------------------------------------------------------------*\
- * int pdf_wrx()
- *
- * Writes a record.
- \*----------------------------------------------------------------------*/
-
- static int
- pdf_wrx(const U_CHAR *x, long nitems, PDFstrm *pdfs)
- {
- int i, result = 0;
-
- if (pdfs->file != NULL) {
- result = fwrite(x, 1, nitems, pdfs->file);
- pdfs->bp += nitems;
- }
- else if (pdfs->buffer != NULL) {
- for (i = 0; i < nitems; i++) {
- if (pdfs->bp >= pdfs->bufmax) {
- pdfs->bufmax += 512;
- #ifdef DEBUG
- fprintf(stderr,
- "pdf_wrx: Increasing buffer to %d bytes\n",
- pdfs->bufmax);
- #endif
- pdfs->buffer = (U_CHAR *)
- realloc((void *) (pdfs->buffer), pdfs->bufmax);
- }
- pdfs->buffer[pdfs->bp++] = x[i];
- }
- result = i;
- }
-
- return result;
- }
-
- /*----------------------------------------------------------------------*\
- * int pdf_rdx()
- *
- * Reads a record.
- \*----------------------------------------------------------------------*/
-
- static int
- pdf_rdx(U_CHAR *x, long nitems, PDFstrm *pdfs)
- {
- int i, result = 0;
-
- if (pdfs->file != NULL) {
- result = fread(x, 1, nitems, pdfs->file);
- pdfs->bp += nitems;
- }
- else if (pdfs->buffer != NULL) {
- for (i = 0; i < nitems; i++) {
- if (pdfs->bp > pdfs->bufmax)
- break;
- x[i] = pdfs->buffer[pdfs->bp++];
- }
- result = i;
- }
-
- return result;
- }
-
- /*----------------------------------------------------------------------*\
- * pdf_wr_header()
- *
- * Writes a header string. Input string must be NULL-terminated. The
- * written string is terminated by a new-line, not a NULL. This is done
- * so you can type e.g. "% strings <file> | head" and get sensible output.
- \*----------------------------------------------------------------------*/
-
- int
- pdf_wr_header(PDFstrm *pdfs, char *header)
- {
- int i;
-
- dbug_enter("pdf_wr_header");
-
- for (i = 0; i < 79; i++) {
- if (header[i] == '\0')
- break;
- if (pdf_putc(header[i], pdfs) == EOF)
- return PDF_WRERR;
- }
- if (pdf_putc('\n', pdfs) == EOF)
- return PDF_WRERR;
-
- return 0;
- }
-
- /*----------------------------------------------------------------------*\
- * int pdf_rd_header
- *
- * Reads a newline-terminated header string from PDFstrm *pdfs, and
- * converts to a usual NULL-terminated string. 80 chars maximum assumed.
- \*----------------------------------------------------------------------*/
-
- int
- pdf_rd_header(PDFstrm *pdfs, char *header)
- {
- int i;
-
- dbug_enter("pdf_rd_header");
-
- for (i = 0; i < 79; i++) {
- if ((header[i] = pdf_getc(pdfs)) == EOF)
- return PDF_RDERR;
-
- if (header[i] == '\n')
- break;
- }
- header[i] = '\0'; /* NULL terminate */
- return 0;
- }
-
- /*----------------------------------------------------------------------*\
- * int pdf_wr_1byte()
- *
- * Writes a U_CHAR as a single byte.
- \*----------------------------------------------------------------------*/
-
- int
- pdf_wr_1byte(PDFstrm *pdfs, U_CHAR s)
- {
- U_CHAR x[1];
-
- x[0] = s;
- if (pdf_wrx(x, 1, pdfs) != 1)
- return PDF_WRERR;
-
- return 0;
- }
-
- /*----------------------------------------------------------------------*\
- * int pdf_rd_1byte()
- *
- * Reads a single byte, storing into a U_CHAR.
- \*----------------------------------------------------------------------*/
-
- int
- pdf_rd_1byte(PDFstrm *pdfs, U_CHAR *ps)
- {
- U_CHAR x[1];
-
- if ( ! pdf_rdx(x, 1, pdfs))
- return PDF_RDERR;
-
- *ps = ((U_CHAR) x[0]);
- return 0;
- }
-
- /*----------------------------------------------------------------------*\
- * pdf_wr_2bytes()
- *
- * Writes a U_SHORT as two single bytes, low end first.
- \*----------------------------------------------------------------------*/
-
- int
- pdf_wr_2bytes(PDFstrm *pdfs, U_SHORT s)
- {
- U_CHAR x[2];
-
- x[0] = (U_CHAR) ((U_LONG) (s & (U_LONG) 0x00FF));
- x[1] = (U_CHAR) ((U_LONG) (s & (U_LONG) 0xFF00) >> 8);
-
- if (pdf_wrx(x, 2, pdfs) != 2)
- return PDF_WRERR;
-
- return 0;
- }
-
- /*----------------------------------------------------------------------*\
- * pdf_rd_2bytes()
- *
- * Reads a U_SHORT from two single bytes, low end first.
- \*----------------------------------------------------------------------*/
-
- int
- pdf_rd_2bytes(PDFstrm *pdfs, U_SHORT *ps)
- {
- U_CHAR x[2];
-
- if ( ! pdf_rdx(x, 2, pdfs))
- return PDF_RDERR;
-
- *ps = 0;
- *ps |= (U_LONG) x[0];
- *ps |= (U_LONG) x[1] << 8;
-
- return 0;
- }
-
- /*----------------------------------------------------------------------*\
- * pdf_wr_2nbytes()
- *
- * Writes n U_SHORT's as 2n single bytes, low end first.
- \*----------------------------------------------------------------------*/
-
- int
- pdf_wr_2nbytes(PDFstrm *pdfs, U_SHORT *s, PLINT n)
- {
- PLINT i;
- U_CHAR x[2];
-
- for (i = 0; i < n; i++) {
- x[0] = (U_CHAR) ((U_LONG) (s[i] & (U_LONG) 0x00FF));
- x[1] = (U_CHAR) ((U_LONG) (s[i] & (U_LONG) 0xFF00) >> 8);
-
- if (pdf_wrx(x, 2, pdfs) != 2)
- return PDF_WRERR;
- }
- return 0;
- }
-
- /*----------------------------------------------------------------------*\
- * pdf_rd_2nbytes()
- *
- * Reads n U_SHORT's from 2n single bytes, low end first.
- \*----------------------------------------------------------------------*/
-
- int
- pdf_rd_2nbytes(PDFstrm *pdfs, U_SHORT *s, PLINT n)
- {
- PLINT i;
- U_CHAR x[2];
-
- for (i = 0; i < n; i++) {
- if ( ! pdf_rdx(x, 2, pdfs))
- return PDF_RDERR;
-
- s[i] = 0;
- s[i] |= (U_SHORT) x[0];
- s[i] |= (U_SHORT) x[1] << 8;
- }
- return 0;
- }
-
- /*----------------------------------------------------------------------*\
- * pdf_wr_4bytes()
- *
- * Writes an unsigned long as four single bytes, low end first.
- \*----------------------------------------------------------------------*/
-
- int
- pdf_wr_4bytes(PDFstrm *pdfs, U_LONG s)
- {
- U_CHAR x[4];
-
- x[0] = (U_CHAR) ((s & (U_LONG) 0x000000FF));
- x[1] = (U_CHAR) ((s & (U_LONG) 0x0000FF00) >> 8);
- x[2] = (U_CHAR) ((s & (U_LONG) 0x00FF0000) >> 16);
- x[3] = (U_CHAR) ((s & (U_LONG) 0xFF000000) >> 24);
-
- if (pdf_wrx(x, 4, pdfs) != 4)
- return PDF_WRERR;
-
- return 0;
- }
-
- /*----------------------------------------------------------------------*\
- * pdf_rd_4bytes()
- *
- * Reads an unsigned long from 4 single bytes, low end first.
- \*----------------------------------------------------------------------*/
-
- int
- pdf_rd_4bytes(PDFstrm *pdfs, U_LONG *ps)
- {
- U_CHAR x[4];
-
- if ( ! pdf_rdx(x, 4, pdfs))
- return PDF_RDERR;
-
- *ps = 0;
- *ps |= (U_LONG) x[0];
- *ps |= (U_LONG) x[1] << 8;
- *ps |= (U_LONG) x[2] << 16;
- *ps |= (U_LONG) x[3] << 24;
-
- return 0;
- }
-
- /*----------------------------------------------------------------------*\
- * Here is the IEEE floating point specification in both 32 bit and 64 bit
- * precisions, from page 9 of "IEEE Standard for Binary Floating-Point
- * Arithmetic", copyright 1985, IEEE Std 754-1985:
- *
- *
- * Single Format
- *
- * msb means most significant bit
- * lsb means least significant bit
- *
- * 1 8 23
- * _____________________________________________________________________
- * | | | |
- * | s | e | f |
- * |___|________________|______________________________________________|
- * msb lsb msb lsb
- *
- *
- *
- * Double Format
- *
- * msb means most significant bit
- * lsb means least significant bit
- *
- * 1 11 52
- * _____________________________________________________________________
- * | | | |
- * | s | e | f |
- * |___|________________|______________________________________________|
- * msb lsb msb lsb
- *
- *
- * (Thanks to: Andy Mai (mai@ncar.ucar.edu))
- *
- *
- * According to "inmos: Transputer instruction set" the IEEE standard
- * specifies the floating format as:
- *
- * s exp frac
- *
- * Where: s = sign bit (1 bit)
- * exp = exponent (8 bits for 32 bit float / 11 bits for 64 bit float)
- * frac = fraction (23 bits for 32 bit float / 52 bits for 64 bit float)
- *
- * value of (s exp frac) = (-1)^s * 1.frac * 2^(exp-bias) ; if exp not 0
- * (-1)^s * 0.frac * 2^(1-bias) ; if exp = 0
- *
- * where bias = 127 for 32 bit float
- * bias = 1023 for 64 bit float
- *
- * (Thanks to: Tom Bjorkholm(TBJORKHOLM@abo.fi))
- *
- \*----------------------------------------------------------------------*/
-
- /*----------------------------------------------------------------------*\
- * int pdf_wr_ieeef()
- *
- * Writes a float in IEEE single precision (32 bit) format.
- \*----------------------------------------------------------------------*/
-
- int
- pdf_wr_ieeef(PDFstrm *pdfs, float f)
- {
- double fdbl, fmant, f_new;
- float fsgl, f_tmp;
- int istat, exp, e_new, e_off, bias = 127;
- U_LONG value, s_ieee, e_ieee, f_ieee;
-
- if (f == 0.0) {
- value = 0;
- return (pdf_wr_4bytes(pdfs, value));
- }
- fsgl = fdbl = f;
- fmant = frexp(fdbl, &exp);
-
- if (fmant < 0)
- s_ieee = 1;
- else
- s_ieee = 0;
-
- fmant = fabs(fmant);
- f_new = 2 * fmant;
- e_new = exp - 1;
-
- if (e_new < 1 - bias) {
- e_off = e_new - (1 - bias);
- e_ieee = 0;
- f_tmp = f_new * pow((double) 2.0, (double) e_off);
- }
- else {
- e_ieee = e_new + bias;
- f_tmp = f_new - 1;
- }
- f_ieee = f_tmp * 8388608; /* multiply by 2^23 */
-
- if (e_ieee > 255) {
- if (debug)
- fprintf(stderr, "pdf_wr_ieeef: Warning -- overflow\n");
- e_ieee = 255;
- }
-
- s_ieee = s_ieee << 31;
- e_ieee = e_ieee << 23;
-
- value = s_ieee | e_ieee | f_ieee;
-
- if ((istat = pdf_wr_4bytes(pdfs, value)))
- return (istat);
-
- if (debug) {
- fprintf(stderr, "Float value (written): %g\n", fsgl);
- print_ieeef(&fsgl, &value);
- }
-
- return 0;
- }
-
- /*----------------------------------------------------------------------*\
- * int pdf_rd_ieeef()
- *
- * Reads a float from a IEEE single precision (32 bit) format.
- \*----------------------------------------------------------------------*/
-
- int
- pdf_rd_ieeef(PDFstrm *pdfs, float *pf)
- {
- double f_new, f_tmp;
- float fsgl;
- int istat, exp, bias = 127;
- U_LONG value, s_ieee, e_ieee, f_ieee;
-
- if ((istat = pdf_rd_4bytes(pdfs, &value)))
- return (istat);
-
- s_ieee = (value & (U_LONG) 0x80000000) >> 31;
- e_ieee = (value & (U_LONG) 0x7F800000) >> 23;
- f_ieee = (value & (U_LONG) 0x007FFFFF);
-
- f_tmp = (double) f_ieee / 8388608.0; /* divide by 2^23 */
-
- if (e_ieee == 0) {
- exp = 1 - bias;
- f_new = f_tmp;
- }
- else {
- exp = (int) e_ieee - bias;
- f_new = 1.0 + f_tmp;
- }
-
- fsgl = f_new * pow(2.0, (double) exp);
- if (s_ieee == 1)
- fsgl = -fsgl;
-
- *pf = fsgl;
-
- if (debug) {
- fprintf(stderr, "Float value (read): %g\n", fsgl);
- print_ieeef(&fsgl, &value);
- }
-
- return 0;
- }
-
- /*----------------------------------------------------------------------*\
- * print_ieeef()
- *
- * Prints binary representation for numbers pointed to by arguments.
- * The first argument is the original float, the second is the
- * IEEE representation. They should be the same on any machine that
- * uses IEEE floats.
- \*----------------------------------------------------------------------*/
-
- static void
- print_ieeef(void *vx, void *vy)
- {
- int i;
- U_LONG f, *x = (U_LONG *) vx, *y = (U_LONG *) vy;
- char bitrep[33];
-
- bitrep[32] = '\0';
-
- f = *x;
- for (i = 0; i < 32; i++) {
- if (f & 1)
- bitrep[32 - i - 1] = '1';
- else
- bitrep[32 - i - 1] = '0';
- f = f >> 1;
- }
- fprintf(stderr, "Binary representation: ");
- fprintf(stderr, "%s\n", bitrep);
-
- f = *y;
- for (i = 0; i < 32; i++) {
- if (f & 1)
- bitrep[32 - i - 1] = '1';
- else
- bitrep[32 - i - 1] = '0';
- f = f >> 1;
- }
- fprintf(stderr, "Converted representation: ");
- fprintf(stderr, "%s\n\n", bitrep);
-
- return;
- }
-
- /*----------------------------------------------------------------------*\
- * plAlloc2dGrid()
- *
- * Allocates a block of memory for use as a 2-d grid of PLFLT's.
- * Resulting array can be indexed as f[i][j] anywhere. This is to be used
- * instead of PLFLT f[nx][ny], which is less useful. Note that this type
- * of allocation is required by the PLPLOT functions which take a 2-d
- * grids of PLFLT's as an argument, such as plcont() and plot3d().
- * Example usage:
- *
- * PLFLT **z;
- *
- * Alloc2dGrid(&z, XPTS, YPTS);
- *
- \*----------------------------------------------------------------------*/
-
- void
- plAlloc2dGrid(PLFLT ***f, PLINT nx, PLINT ny)
- {
- PLINT i;
-
- *f = (PLFLT **) malloc(nx * sizeof(PLFLT *));
- for (i = 0; i < nx; i++) {
- (*f)[i] = (PLFLT *) malloc(ny * sizeof(PLFLT));
- }
- }
-
- /*----------------------------------------------------------------------*\
- * Free2dGrid()
- *
- * Frees a block of memory allocated with Alloc2dGrid().
- \*----------------------------------------------------------------------*/
-
- void
- plFree2dGrid(PLFLT **f, PLINT nx, PLINT ny)
- {
- PLINT i;
-
- for (i = 0; i < nx; i++)
- free((void *) f[i]);
-
- free((void *) f);
- }
-